import { isMac } from "@renderer/config/constant";
import { useTabs } from "@renderer/queries";
import { useAppScopeShortcuts } from "@renderer/queries/hooks/use-shortcuts";
import { EventNames, emitter } from "@renderer/services/event-service";
import logger from "@shared/logger/renderer-logger";
import { useCallback, useEffect, useState } from "react";
import { useLocation } from "react-router-dom";

export function useAppShortcutListenser() {
  const { data: appShortcuts } = useAppScopeShortcuts();
  const { data: tabs = [] } = useTabs();

  const [isRecording, setIsRecording] = useState(false);

  const location = useLocation();
  const isShortcutsSettingsPage = location.pathname.includes(
    "/settings/shortcuts-settings",
  );

  const shouldTriggerCmdW = useCallback(
    (action: string) => action === "close-current-tab" && tabs.length === 0,
    [tabs.length],
  );

  const handleKeyDown = useCallback(
    (event: KeyboardEvent) => {
      if (isShortcutsSettingsPage && isRecording) {
        event.preventDefault();
        return;
      }

      if (event.isComposing) return;

      const pressedKeys: string[] = [];

      if (isMac) {
        if (event.metaKey) pressedKeys.push("Cmd");
        if (event.ctrlKey) pressedKeys.push("Ctrl"); // Mac 上 Ctrl 仍然是 Ctrl
        if (event.altKey) pressedKeys.push("Option");
      } else {
        if (event.ctrlKey) pressedKeys.push("Ctrl");
        if (event.metaKey) pressedKeys.push("Meta"); // Windows/Linux 上的 Meta 键
        if (event.altKey) pressedKeys.push("Alt");
      }

      if (event.shiftKey) {
        pressedKeys.push("Shift");
      }

      if (
        event.key &&
        !["Control", "Meta", "Shift", "Alt", "Option"].includes(event.key)
      ) {
        let key = event.key;
        if (key === " ") key = "Space";
        else if (key === "Enter") key = "Enter";
        else if (key === "Backspace") key = "Backspace";
        else if (key === "Tab") key = "Tab";
        else if (key === "Escape") key = "Escape";
        else if (key === ",") key = ",";
        else key = event.code.replace(/^(Key|Digit|Numpad)/, "").toUpperCase();

        pressedKeys.push(key);
      }

      if (pressedKeys.length === 0) return;

      for (const shortcut of appShortcuts || []) {
        const shortcutKeys = Array.from(shortcut.keys);

        // 检查直接匹配
        if (arraysEqual(shortcutKeys, pressedKeys)) {
          if (shouldTriggerCmdW(shortcut.action)) {
            logger.info("Triggering 'cmd + w' action for close the window");
            return;
          }

          event.preventDefault();
          event.stopPropagation();

          emitter.emit(EventNames.SHORTCUT_TRIGGERED, {
            action: shortcut.action,
          });
          return;
        }

        const compatibleKeyCombinations = generateCompatibleKeys(shortcutKeys);

        for (const compatibleKeys of compatibleKeyCombinations) {
          if (arraysEqual(compatibleKeys, pressedKeys)) {
            event.preventDefault();
            event.stopPropagation();

            emitter.emit(EventNames.SHORTCUT_TRIGGERED, {
              action: shortcut.action,
            });
            return;
          }
        }
      }
    },
    [appShortcuts, isShortcutsSettingsPage, isRecording, shouldTriggerCmdW],
  );

  useEffect(() => {
    document.addEventListener("keydown", handleKeyDown, true);
    return () => {
      document.removeEventListener("keydown", handleKeyDown, true);
    };
  }, [handleKeyDown]);

  useEffect(() => {
    const unsubs = [
      emitter.on(EventNames.SHORTCUT_RECORDING_START, () => {
        setIsRecording(true);
      }),
      emitter.on(EventNames.SHORTCUT_RECORDING_STOP, () => {
        setIsRecording(false);
      }),
    ];

    return () =>
      unsubs.forEach((unsub) => {
        unsub();
      });
  }, []);
}

function arraysEqual(a: string[], b: string[]): boolean {
  if (a.length !== b.length) return false;

  const sortedA = [...a].sort();
  const sortedB = [...b].sort();

  return sortedA.every((val, index) => val === sortedB[index]);
}

function generateCompatibleKeys(keys: string[]): string[][] {
  const combinations: string[][] = [];

  const keyMappings = {
    Cmd: isMac ? ["Cmd"] : ["Cmd", "Ctrl"],
    Ctrl: isMac ? ["Ctrl"] : ["Ctrl", "Cmd"],
    Option: ["Option", "Alt"],
    Alt: ["Alt", "Option"],
  };

  function generateCombinations(
    keyIndex: number,
    currentCombination: string[],
  ): void {
    if (keyIndex >= keys.length) {
      combinations.push([...currentCombination]);
      return;
    }

    const currentKey = keys[keyIndex];
    const possibleKeys = keyMappings[
      currentKey as keyof typeof keyMappings
    ] || [currentKey];

    for (const possibleKey of possibleKeys) {
      currentCombination[keyIndex] = possibleKey;
      generateCombinations(keyIndex + 1, currentCombination);
    }
  }

  generateCombinations(0, new Array(keys.length));

  return combinations.filter((combo) => !arraysEqual(combo, keys));
}
